home *** CD-ROM | disk | FTP | other *** search
/ CGI How-To / CGI HOW-TO.iso / chap4 / 4_6 / dyn_c / cgilib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-15  |  12.5 KB  |  654 lines

  1.  
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "cgilib.h"
  6.  
  7. #define NEEDS_ENCODE(x) (!(islower(x)||isupper(x)||isdigit(x)||(x==' ')))
  8.  
  9. void decodeData(char *queryString)
  10. {
  11.     /* Temporary variables */
  12.     int i = 0, j = 0, max = 0;
  13.     char c;
  14.     
  15.     /*
  16.     * Loop over the string.
  17.     * We use two loop indices,
  18.     * i is the actual current character
  19.     * j is used to move ahead when hex codes are found
  20.     * Two indices are needed since the string shrinks
  21.     * as hex-codes are turned into single characters.
  22.     * The loop ends when the '\0' character has been "copied".
  23.     */
  24.     if(queryString) max = strlen(queryString) + 1;
  25.     
  26.     for (i=0, j=0; j < max; ++i, ++j) 
  27.     {
  28.         /* If we have found hex-codes, j>i so copy the data down. */
  29.         
  30.         queryString[i] = queryString[j];
  31.         
  32.         if ('+' == queryString[i]) /* Convert pluses to spaces */
  33.         {
  34.             queryString[i] = ' ';
  35.         }
  36.         else if ('%' == queryString[j])/* Convert hex codes */
  37.         {
  38.             /*
  39.             * Get the first number of the hex code, and store it
  40.             * as a char.
  41.             */
  42.             
  43.             c = ((queryString[j+1] >= 'A') ?
  44.                         ((queryString[j+1] & 0xdf) - 'A') + 10 
  45.                         : (queryString[j+1] - '0'));
  46.             /*
  47.             * The first hex-code was the 16 places, so multiply
  48.             * c by 16.
  49.             */
  50.                             
  51.             c *= 16;
  52.             
  53.             /*
  54.             * Get the second number in the hex code and add that
  55.             * to the value of c.
  56.             * c now stores the correct character for the hex code.
  57.             */
  58.             c += ((queryString[j+2] >= 'A') ? 
  59.                         ((queryString[j+2] & 0xdf) - 'A') + 10 
  60.                         : (queryString[j+2] - '0'));
  61.                             
  62.             /* Replace the % char we copied with the actual character. */                
  63.             queryString[i] = c;
  64.     
  65.             /* Move j past the hex-code */
  66.             j += 2;
  67.         }
  68.     }
  69. }
  70.  
  71. /* encodeData() encodes a string for CGI */
  72. void encodeData(String aString)
  73. {
  74.   int x,size,l,push = 0;
  75.  
  76.   if(aString->string != NULL)
  77.     {
  78.       
  79.       /* figure out the size after encoding */
  80.       l=string_length(aString);
  81.       
  82.       for(x=0;x<l;x++)
  83.     {
  84.       if(NEEDS_ENCODE(aString->string[x]))
  85.         {
  86.           push+=2;
  87.         }
  88.       
  89.     }
  90.       
  91.       /* If we encountered characters to encode, encode them */
  92.       if(push != 0)
  93.     {
  94.       /* Grow as needed */
  95.       string_setSize(aString,l+push+1,0);
  96.       
  97.       /* Start encoded, back to front to reduce copying */
  98.       for(x=l;x>=0;x--)
  99.         {
  100.           
  101.           if((NEEDS_ENCODE(aString->string[x]))
  102.          &&(aString->string[x] != '\0'))
  103.            {
  104.              int tmp;
  105.              
  106.              tmp = (aString->string[x])%16;
  107.              aString->string[x+push] = (tmp>=10)? (tmp-10 + 'A') : (tmp+'0');
  108.              push--;
  109.  
  110.              tmp = (aString->string[x])/16;
  111.              aString->string[x+push] = (tmp>=10)? (tmp-10 + 'A') : (tmp+'0');
  112.  
  113.              push--;
  114.              aString->string[x+push] = '%';
  115.            }
  116.           else/*push the other char back*/
  117.         {
  118.           aString->string[x+push] = aString->string[x];
  119.         }
  120.         }
  121.     }
  122.  
  123.       /*Convert the spaces to pluses */
  124.       for(x=0;aString->string[x] != '\0';x++)
  125.     {
  126.       if(aString->string[x] == ' ') aString->string[x] = '+';
  127.     }
  128.       
  129.     } 
  130. }
  131.  
  132. /* 
  133.  * encodeDictionary() encodes a dictionary in the form
  134.  * of CGI data.
  135.  */
  136. String encodeDictionary(Dictionary dataDict)
  137. {
  138.   String returnString = 0;
  139.   DictState state;
  140.   char *key;
  141.   void *value;
  142.   String buffer;
  143.   int needAmp = 0;
  144.  
  145.   /* allocate the string */
  146.   returnString = string_alloc(512);
  147.   buffer = string_alloc(128);
  148.  
  149.   /* Create a dictionary state */
  150.   state = dict_initState(dataDict);
  151.  
  152.   /* Calculate how long the string will be */
  153.   
  154.   while(dict_nextState(&state))
  155.     {
  156.       key = state.curNode->key;
  157.  
  158.       /* If this isn't a multiple value, encode and append it */
  159.       if(key && strncmp(key,"A_",2))
  160.      {
  161.        value = state.curNode->value;
  162.  
  163.        string_setStringValue(buffer,key);
  164.        encodeData(buffer);
  165.  
  166.        if(needAmp)
  167.          {
  168.            string_appendChar(returnString,'&');
  169.          }
  170.  
  171.        string_appendString(returnString,buffer->string);
  172.        string_appendChar(returnString,'=');
  173.  
  174.        if(value)
  175.          {
  176.            string_setStringValue(buffer,value);
  177.            encodeData(buffer);
  178.          }
  179.        else
  180.          {
  181.            string_empty(buffer);
  182.          }
  183.  
  184.        string_appendString(returnString,buffer->string);
  185.  
  186.        needAmp = 1;
  187.      }
  188.     }
  189.  
  190.   string_free(buffer);
  191.   return returnString;
  192. }
  193.  
  194. int parseData(char *queryString, Dictionary dataDict)
  195. {
  196.     /* Temporary variables */
  197.     char *cursor = (char *)0;
  198.     
  199.     char *key = (char *)0, *value = (char *)0;
  200.     
  201.     char *sbegin = (char *)0, *send = (char *)0;
  202.     
  203.     int charsToCopy = 0;
  204.  
  205.     /* For example take queryString = "key=value&key1=value1" */
  206.     
  207.     if(queryString != (char *)0)
  208.       {
  209.         cursor = queryString;
  210.       }
  211.     else
  212.       {
  213.         return 0;
  214.       }
  215.  
  216.     do{/* Loop while we are finding keys */
  217.         
  218.         key = 0;/* Reset the tmp key */
  219.         
  220.         value = 0;/* Reset the tmp value */
  221.         
  222.         /*
  223.          * Reset the search pointer, sbegin 
  224.          *
  225.          *   key=value&key1=value1
  226.          *   ^         ^
  227.          *   |         |
  228.          *  pass 1    pass 2
  229.          *
  230.          */
  231.          
  232.         sbegin = cursor;
  233.         
  234.         /* 
  235.          * Move sbegin past any next special char, & or =
  236.          *
  237.          *   key=value&key1=value1
  238.          *   ^         ^
  239.          *   |         |
  240.          *  pass 1    pass 2
  241.          *
  242.          */
  243.         
  244.         sbegin += strspn(sbegin, "=&");
  245.         
  246.         /* Check if we are at the end of the query string */
  247.         
  248.         if(*sbegin == '\0') /* If at end, make the key and cursor = NULL */
  249.         {
  250.             cursor = (char *) 0;
  251.             key = cursor;
  252.         }
  253.         else /* Otherwise, find the key */
  254.         {
  255.             /* Reset the number of characters in the key */
  256.             
  257.             charsToCopy = 0;
  258.             
  259.             
  260.             /*
  261.              * Find the end of the key
  262.              *
  263.              *   key=value&key1=value1
  264.              *      ^          ^
  265.              *      |          |
  266.              *     pass 1     pass 2
  267.              *
  268.              */
  269.             send = sbegin + strcspn(sbegin,"=&");
  270.             
  271.             /* Check if the end of the key is the end of the string */
  272.             
  273.             if('\0' != (*send)) /* If not, calculate the length of key */
  274.             {
  275.                 /*
  276.                  * Find send past the =
  277.                  *
  278.                  *   key=value&key1=value1
  279.                  *       ^          ^
  280.                  *       |          |
  281.                  *      pass 1     pass 2
  282.                  *
  283.                  */
  284.                 send++;
  285.                 charsToCopy = strlen(sbegin) - strlen(send) - 1;
  286.             }
  287.             else /* Otherwise, key is whats left */
  288.             {
  289.                 charsToCopy = strlen(sbegin);
  290.             }
  291.             
  292.             /* Move the cursor to the end of the key */
  293.             
  294.             cursor = send;
  295.             
  296.             /* Allocate memory for the key */
  297.             
  298.             key = (char *) malloc(sizeof(char)*(charsToCopy +1));
  299.             
  300.             /* Copy the correst number of characters to the key string */
  301.             
  302.             strncpy(key,sbegin,charsToCopy);
  303.             
  304.             /* End the key string with a '\0' */
  305.             
  306.             key[charsToCopy] = '\0';
  307.         }
  308.         
  309.         /* If we have a key, try to read the value */
  310.         
  311.         if( key && (*key != '\0')){
  312.             
  313.             /*
  314.              * See if the next character is a &,
  315.              * if it is the key has an empty value.
  316.              */
  317.                 
  318.             if(('\0' != *cursor)
  319.                     &&('&' != *cursor))
  320.             {
  321.                 /*
  322.                  * Find the beginning of the value
  323.                  *
  324.                  *   key=value&key1=value1
  325.                  *       ^          ^
  326.                  *       |          |
  327.                  *      pass 1     pass 2
  328.                  *
  329.                  */
  330.                 
  331.                 sbegin = cursor;
  332.                 sbegin += strspn(sbegin, "=&");
  333.                 
  334.                 /* Check if we found a vlaue */
  335.                 
  336.                 if(*sbegin == '\0') /* If not set the value and cursor to 0 */
  337.                 {
  338.                     cursor = (char *) 0;
  339.                     value = cursor;
  340.                 }
  341.                 else /* Otherwise, find the value */
  342.                 {
  343.                     /* Reset the length of the value string */
  344.                 
  345.                     charsToCopy = 0;
  346.                     
  347.                     /*
  348.                      * Find the end of the value
  349.                      *
  350.                      *   key=value&key1=value1
  351.                      *            ^           ^
  352.                      *            |           |
  353.                      *           pass 1      pass 2
  354.                      *
  355.                      */
  356.                      
  357.                     send = sbegin + strcspn(sbegin,"=&");
  358.                     
  359.                     /* Check if the value is at the end of the string */
  360.                     
  361.                     if('\0' != (*send)) /* If not, calculate the length */
  362.                     {
  363.                         /*
  364.                         * Move send past the &
  365.                         *
  366.                         *   key=value&key1=value1
  367.                         *       ^          ^
  368.                         *       |          |
  369.                         *      pass 1     pass 2
  370.                         *
  371.                         */
  372.                         send++;
  373.                         charsToCopy = strlen(sbegin) 
  374.                                     - strlen(send) - 1;
  375.                     }
  376.                     else /* Otherwise, the length is from the start to '\0'*/
  377.                     {
  378.                         charsToCopy = strlen(sbegin);
  379.                     }
  380.                     
  381.                     /*
  382.                      * Reset the cursor
  383.                      *
  384.                      *   key=value&key1=value1
  385.                      *            ^           ^
  386.                      *            |           |
  387.                      *           pass 1      pass 2
  388.                      *
  389.                      */
  390.                     
  391.                     cursor = send;
  392.                     
  393.                     /* Allocate space for the value string */
  394.                     
  395.                     value = (char *) 
  396.                         malloc(sizeof(char)*(charsToCopy +1));
  397.                     
  398.                     /* Copy the value string, and add a '\0' */
  399.                     
  400.                     strncpy(value,sbegin,charsToCopy);
  401.                     value[charsToCopy] = '\0';
  402.                 }
  403.                 
  404.                 /*
  405.                  * Decode the key and value then,
  406.                  * print them
  407.                  */
  408.                  
  409.                 decodeData(key);
  410.                 decodeData(value);
  411.                 
  412.             }
  413.             else/* Key has an empty value */
  414.             {
  415.                 /*
  416.                  * Decode the key, then
  417.                  * print the key and an empty value
  418.                  */
  419.                 
  420.                 decodeData(key);
  421.                 
  422.                 value = malloc(sizeof(char) * 1);
  423.                 value[0] = '\0';
  424.             }
  425.             
  426.             /*
  427.              * Insert the value into the dictionary, but
  428.              * allow for multiple values on key.
  429.              * Put multiple values into an Array, with the key,
  430.              * A_key.
  431.              */
  432.              
  433.             /* Check if this is a multiple value */
  434.             if(dict_isKey(dataDict,key))
  435.             {
  436.                 /* Create the name for the array key */
  437.                 char *aName;
  438.                 
  439.                 aName = (char *) malloc((strlen(key)+3) * sizeof(char));
  440.                 
  441.                 sprintf(aName,"A_%s",key);
  442.                 
  443.                 /* Check if the array is in the dict, already */
  444.                 
  445.                 if(dict_isKey(dataDict,aName))
  446.                 {
  447.                     /* Add the new value to the array */
  448.                     
  449.                     Array theArray = 0;
  450.                     
  451.                     theArray = (Array) dict_valueForKey(dataDict,aName);
  452.                 
  453.                     array_addItem(theArray,value);
  454.                     
  455.                     /* Set the dictionaries value, to the latest */
  456.                     
  457.                     dict_setValueForKey(dataDict, key, value);
  458.                     
  459.                 }
  460.                 else /* If not, ... */
  461.                 {
  462.                     /* Create the array */
  463.                     
  464.                     Array theArray = 0;
  465.                     
  466.                     theArray = array_alloc(3);
  467.                     
  468.                     /* Add the first value to the array */
  469.                     
  470.                     array_addItem(theArray, dict_valueForKey(dataDict,key));
  471.                     
  472.                     /* Add the new value to the array */
  473.                     
  474.                     array_addItem(theArray,value);
  475.                     
  476.                     /* Set the dictionaries value, to the latest */
  477.                     
  478.                     dict_setValueForKey(dataDict, key, value);
  479.                     
  480.                     /* Add the array to the dictionary */
  481.                     
  482.                     dict_setValueForKey(dataDict, aName, (void *)theArray);
  483.                     
  484.                 }
  485.                 
  486.                 
  487.                 free(aName);
  488.             }
  489.             else /* If not, simple insert the value */
  490.             {
  491.                 dict_setValueForKey(dataDict, key, value);
  492.             }
  493.         
  494.         }
  495.     
  496.     }while(key && ('\0' != *key) && ('\0' != *cursor));
  497.         
  498.     return 1;/* Return 1 for success */
  499. }
  500.  
  501. void readGetData(char **aString)
  502. {
  503.     /* The data after it is read in */
  504.     char *queryString;
  505.     int len = 0;
  506.  
  507.     queryString = getenv("QUERY_STRING");
  508.  
  509.     if(queryString)
  510.       {    
  511.         len = strlen(queryString);
  512.  
  513.         *aString = malloc(sizeof(char) * len);
  514.  
  515.         strcpy(*aString,queryString);
  516.       }
  517.     else
  518.       {
  519.         len = 1;
  520.  
  521.         *aString = malloc(sizeof(char) * len);
  522.  
  523.         **aString = '\0';
  524.       }
  525. }
  526. void readPostData(char **aString)
  527. {
  528.     /* The data after it is read in */
  529.     char *queryString;
  530.     
  531.     /* The amount of data to read */
  532.     int contentLength;
  533.  
  534.     /* Temporary variables for storing envvar and iterating */
  535.     char *sizeString;
  536.     int i;
  537.     
  538.     /* Read the environment variable CONTENT_LENGTH */
  539.     
  540.     sizeString = getenv("CONTENT_LENGTH");
  541.     
  542.     
  543.     /* If the env. var. existed, convert the string to an integer */
  544.     
  545.     if (sizeString)
  546.     {
  547.         contentLength = atoi( sizeString );
  548.     }
  549.     else
  550.     {
  551.         contentLength = 0;
  552.     }
  553.     
  554.     /*
  555.      * If there is a non-zero amount of data, 
  556.      * alloc a string big enough to hold it.
  557.      */
  558.     if ( 0 != contentLength)
  559.     {
  560.         /* Notice that we add one to hold the null, '\0', character. */
  561.         queryString = (char *) malloc(sizeof(char) * (contentLength + 1) );
  562.     }
  563.     else
  564.     {
  565.         queryString = (char *) 0;
  566.     }
  567.     
  568.     /* If the malloc succeeded, read the data. */
  569.     
  570.     if ( queryString )
  571.     {
  572.         i = 0;
  573.         
  574.         /*
  575.          * Use fgetc to read the data, 
  576.          * iterating until the exact number of characters is read.
  577.         */
  578.         while( i < contentLength)
  579.         {
  580.                 queryString[ i++ ] = fgetc(stdin);
  581.         }
  582.         
  583.         /* Add the null, '\0', character to the end. */
  584.         
  585.         queryString[ i ] = '\0';
  586.     
  587.         /* Set the arguement to point to the data. */
  588.     
  589.         *aString = queryString;
  590.  
  591.     }
  592.     else
  593.         {
  594.         *aString = malloc(sizeof(char));
  595.  
  596.         **aString = '\0';
  597.         }
  598. }
  599.  
  600. void readData(char **aString)
  601. {
  602.     char *requestType = (char *) 0;
  603.     
  604.     
  605.     /* Read the request type */
  606.     
  607.     requestType = getenv("REQUEST_METHOD");
  608.     
  609.     /*
  610.      * If it is a GET request use readGetData,
  611.      * otherwise, if it is a POST request, use readPostData.
  612.      */
  613.      
  614.     if(requestType && !strcmp(requestType,"GET"))
  615.     {
  616.         readGetData(aString);
  617.     }
  618.     else if(requestType && !strcmp(requestType,"POST"))
  619.     {
  620.         readPostData(aString);
  621.     }
  622.     else
  623.     {
  624.              *aString = malloc(sizeof(char));
  625.  
  626.         **aString = '\0';
  627.     }
  628. }
  629.  
  630. Dictionary readParse()
  631. {
  632.     Dictionary returnData;
  633.     char *data;
  634.     
  635.     returnData = dict_alloc();
  636.       
  637.      readData(&data);
  638.           
  639.     if(data) parseData(data, returnData);
  640.     
  641.     if(data) free(data);
  642.     
  643.     return returnData;
  644. }
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.